package com.app.util;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;

public class RenewalContractGenerator {

    // 定义字体
    private static Font titleFont;
    private static Font contentFont;
    private static Font signatureLabelFont;

    static {
        try {
            // 初始化中文字体
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            titleFont = new Font(bfChinese, 18, Font.BOLD);
            contentFont = new Font(bfChinese, 12, Font.NORMAL);
            signatureLabelFont = new Font(bfChinese, 10, Font.ITALIC);
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }
    }

    public static String generatePdf(String originalPdfPath) throws Exception {
        String filePath = System.getProperty("user.dir") + File.separator + "file" + File.separator + originalPdfPath + ".pdf";
        // 生成原始合同
        generateRenewalContract(filePath);
        System.out.println("原始合同已生成: " + filePath);
        return filePath;
    }

    /**
     * 在签订时，写一个方法，将模版中的内容替换为真实用户签订的内容，生成pdf进行保存，然后给前端将pdf转为图片。
     * 在前端完成签名后，将签名的图片传过来然后添加进pdf进行保存，删除之前的pdf
     */
    public static void main(String[] args) {

        try {
            // 定义文件路径
            String baseDir = "D:/WorkPlace/suzhouHousesLease/api/file/";
            String originalPdfPath = baseDir + "contract_original.pdf";
            String lessorSignaturePath = baseDir + "Snipaste_2025-04-18_16-16-25.png";
            String lesseeSignaturePath = baseDir + "Snipaste_2025-04-18_16-16-25.png";
            String finalPdfPath = baseDir + "contract_final.pdf";
            String tempPdfPath = baseDir + "contract_temp.pdf";

            // 检查并创建目录
            ensureDirectoryExists(baseDir);

            // 生成原始合同
            generateRenewalContract(originalPdfPath);
            System.out.println("原始合同已生成: " + originalPdfPath);

            // 签名位置参数
            float lessorX = 100, lessorY = 150;
            float lesseeX = 300, lesseeY = 150;
            float signatureWidth = 80;
            float signatureHeight = 40;

            // 插入甲方签名
            insertSignatureImage(originalPdfPath, tempPdfPath, lessorSignaturePath,
                    1, lessorX, lessorY, signatureWidth, signatureHeight);

            // 插入乙方签名
            insertSignatureImage(tempPdfPath, finalPdfPath, lesseeSignaturePath,
                    1, lesseeX, lesseeY, signatureWidth, signatureHeight);

            System.out.println("合同已成功生成并添加签名: " + finalPdfPath);

        } catch (Exception e) {
            handleError(e);
        }
    }

    /**
     * 确保目录存在且有写入权限
     */
    private static void ensureDirectoryExists(String dirPath) throws IOException {
        Path path = Paths.get(dirPath);
        if (!Files.exists(path)) {
            try {
                Files.createDirectories(path);
            } catch (IOException e) {
                System.err.println("无法创建目录: " + dirPath);
                throw e;
            }
        }

        // 检查写入权限
        if (!Files.isWritable(path)) {
            throw new IOException("没有目录写入权限: " + dirPath);
        }
    }

    /**
     * 生成续租合同
     */
    public static void generateRenewalContract(String outputPath) throws Exception {
        Document document = null;
        FileOutputStream fos = null;
        PdfWriter writer = null;

        try {
            document = new Document(PageSize.A4);
            fos = new FileOutputStream(outputPath);
            writer = PdfWriter.getInstance(document, fos);
            document.open();

            // 添加标题
            Paragraph title = new Paragraph("房屋续租合同", titleFont);
            title.setAlignment(Element.ALIGN_CENTER);
            document.add(title);

            // 添加续租条款
            String[] clauses = {
                    "鉴于甲乙双方于____年____月____日签订的《房屋租赁合同》（以下称'原合同'）将于____年____月____日到期，",
                    "现双方根据平等自愿原则，就原合同的续签事宜，经双方协商一致签订本合同。",
                    "",
                    "第一条 甲方无须向乙方退还根据原合同已支付的租赁押金（____元）。该租赁押金转为本合同租赁押金。",
                    "",
                    "第二条 甲方将原合同标的房屋继续出租给乙方使用，租金每月____元（含税）。",
                    "",
                    "第三条 续租期为12个月：自____年____月____日起至____年____月____日止。",
                    "",
                    "第四条 如乙方在续租期内不再承租房屋的，应提前15日书面通知甲方。",
                    "",
                    "第五条 租金按每三个月结算一次。乙方应于每季度的第一个工作日前将本季度房屋租金支付给甲方。",
                    "",
                    "第六条 乙方按原合同约定已交给甲方的押金继续由甲方保管。",
                    "",
                    "第七条 违约责任",
                    "1. 非乙方原因造成乙方不能正常使用房屋的，乙方可免交期间租金。",
                    "2. 乙方未按约定支付租金的，每逾期一日需按应付未付租金0.5%标准支付违约金。",
                    "",
                    "第八条 本合同未说明之双方权利义务及有关约定按双方于原合同执行。"
            };

            for (String clause : clauses) {
                document.add(new Paragraph(clause, contentFont));
            }

            // 添加签名区域
            addSignatureArea(document);

        } finally {
            // 手动关闭资源，确保正确关闭顺序
            if (document != null) {
                document.close();
            }
            if (writer != null) {
                writer.close();
            }
            if (fos != null) {
                fos.close();
            }
        }
    }

    private static void addSignatureArea(Document document) throws DocumentException {
        document.add(new Paragraph(" "));
        document.add(new Paragraph(" "));

        PdfPTable table = new PdfPTable(2);
        table.setWidthPercentage(80);
        table.setHorizontalAlignment(Element.ALIGN_CENTER);

        // 甲方签名区域
        PdfPCell lessorCell = createSignatureCell("甲方（盖章/签名）：");
        table.addCell(lessorCell);

        // 乙方签名区域
        PdfPCell lesseeCell = createSignatureCell("乙方（盖章/签名）：");
        table.addCell(lesseeCell);

        // 签署日期
        PdfPCell dateCell = new PdfPCell(new Phrase("签署日期：____年____月____日", contentFont));
        dateCell.setColspan(2);
        dateCell.setBorder(Rectangle.NO_BORDER);
        dateCell.setHorizontalAlignment(Element.ALIGN_CENTER);
        table.addCell(dateCell);

        document.add(table);
    }

    private static PdfPCell createSignatureCell(String label) {
        PdfPCell cell = new PdfPCell();
        cell.setBorder(Rectangle.BOTTOM);
        cell.setFixedHeight(100);
        cell.setPaddingBottom(10);
        cell.addElement(new Paragraph(label, contentFont));
        cell.addElement(new Paragraph("[签名图片位置]", signatureLabelFont));
        return cell;
    }

    /**
     * 在PDF指定位置插入签名图片
     */
    public static void insertSignatureImage(String originalPdfPath, String outputPdfPath,
                                            String signatureImagePath, int pageNumber,
                                            float x, float y, float width, float height) throws Exception {
        PdfReader reader = null;
        FileOutputStream fos = null;
        PdfStamper stamper = null;

        try {
            // 检查签名图片是否存在
            if (!Files.exists(Paths.get(signatureImagePath))) {
                throw new IOException("签名图片不存在: " + signatureImagePath);
            }

            reader = new PdfReader(originalPdfPath);
            fos = new FileOutputStream(outputPdfPath);
            stamper = new PdfStamper(reader, fos);

            // 获取指定页面的内容
            PdfContentByte content = stamper.getOverContent(pageNumber);

            // 加载签名图片
            Image signature = Image.getInstance(signatureImagePath);

            // 设置签名位置和大小
            signature.setAbsolutePosition(x, y);
            signature.scaleToFit(width, height);

            // 添加签名图片
            content.addImage(signature);

        } finally {
            // 手动关闭资源，确保正确关闭顺序
            if (stamper != null) {
                stamper.close();
            }
            if (reader != null) {
                reader.close();
            }
            if (fos != null) {
                fos.close();
            }
        }
    }

    /**
     * 错误处理
     */
    private static void handleError(Exception e) {
        System.err.println("生成合同失败: " + e.getMessage());
        e.printStackTrace();

        // 回退方案 - 生成到用户目录
        try {
            String userHome = System.getProperty("user.home");
            String finalPath = userHome + "/contract_final.pdf";

            generateRenewalContract(finalPath);
            System.out.println("合同已生成到用户目录: " + finalPath);
        } catch (Exception ex) {
            System.err.println("无法在任何位置生成合同: " + ex.getMessage());
        }
    }
}